package com.neusoft.hifly.commons.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.Key;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Vector;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.commons.lang3.StringUtils;

import com.neusoft.hifly.commons.exception.SystemErrorException;
import com.neusoft.hifly.commons.id.IdWorker;
import com.neusoft.hifly.commons.lang.LocalDateUtil;
import com.neusoft.hifly.core.log.Log;

/**
 * Title: 核心类库
 * <p>
 * Description: 处理文件类
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 东软汉枫
 *
 * @author lh_neu
 * @version 1.0.0
 */
public final class FileUtil extends FilenameUtils {
	private static Map<String, List<String>> fileMap; // 读取文件返回的结果
	private static List<String> folders; // 文件夹结合
	private static List<String> files; // 文件集合
	private static List<String> fileNames; // 文件名集合
	private static List<String> times; // 时间集合

	/**
	 * 默认的构造方法
	 */
	private FileUtil() {
	}

	/**
	 * 获取到WEB-INF/classes下
	 *
	 * @return WEB-INF/classes 目录
	 */
	public static String getWebClassesPath() {
		//Class文件所在路径
		// 将有空格的目录获取是将空格替换成%20了，这里需要替换回来 @lihui 2013-9-4
		return StringUtils.replace(Thread.currentThread().getContextClassLoader().getResource("").getPath(), "%20",
				" ");
	}

	/**
	 * 判断文件是否存在
	 *
	 * @param path
	 *            文件路径（带扩展名）
	 * @return 是否存在
	 */
	public static boolean exists(final String path) {
		if (StringUtils.isNotBlank(path)) {
			final File file = new File(path);
			return file.exists();
		} else {
			Log.error("路径  {}. 无法判断文件是否存在!", new Object[] { path });
			return false;
		}
	}

	/**
	 * 检测路径是否存在，不存在则创建
	 *
	 * @param path
	 *            路径
	 */
	public synchronized static void makeDir(final String path) {
		if (StringUtils.isNotBlank(path)) {
			final File file = new File(path);
			if (!(file.isDirectory()) && !file.exists()) { // 判断文件夹是否存在
				file.mkdirs(); // 创建文件夹包括创建必需但不存在的父目录
			}
		} else {
			Log.error("路径  {}. 无法创建路径!", new Object[] { path });
		}
	}

	/**
	 * 刪除指定路径的文件
	 *
	 * @param file
	 *            指定路径的文件
	 */
	public synchronized static void delFile(final String file) {
		try {
			if (StringUtils.isNotBlank(file)) {
				final File f = new File(file); // 导入一个文件
				if (f.exists()) { // 如果存在该文件
					if (f.isFile()) {
						// 删除文件
						if (f.delete()) {
							Log.debug("文件：{} 删除文件成功!", new Object[] { file });
						} else {
							Log.debug("文件：{} 删除文件失败!", new Object[] { file });
						}
					} else {
						// 删除文件夹下的内容
						FileUtil.delAllFile(file);
						// 删除文件夹
						f.delete();
					}
				}
			} else {
				Log.error("文件：{} 无法删除文件!", new Object[] { file });
			}
		} catch (final Exception e) {

		}
	}

	/**
	 * 删除文件夹里面的所有文件
	 *
	 * @param path
	 *            String 文件夹路径 如 c:/fqf
	 */
	public synchronized static void delAllFile(final String path) {
		final File file = new File(path);
		if (!file.exists()) {
			return;
		}
		if (!file.isDirectory()) {
			return;
		}
		final String[] tempList = file.list();
		File temp = null;
		for (final String element : tempList) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + element);
			} else {
				temp = new File(path + File.separator + element);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				FileUtil.delAllFile(path + File.separator + element); // 先删除文件夹里面的文件
				temp.delete(); // 再删除空文件夹
			}
		}
	}

	/**
	 * 创建文件
	 *
	 * @param path
	 *            文件路径
	 * @param fileName
	 *            文件名（带扩展名）
	 * @return File
	 */
	public synchronized static File makeFile(String path, final String fileName) {
		if (StringUtils.isNotBlank(fileName) && StringUtils.isNotBlank(path)) {
			File file;
			FileUtil.makeDir(path);
			path += File.separator + fileName;
			file = new File(path);
			try {
				file.createNewFile(); // 创建文件
				Log.debug("创建文件 {} 成功!", new Object[] { path });
			} catch (final IOException e) {
				Log.error("创建文件 {} 失败!", new Object[] { path });
				Log.error(e.getMessage());
			}
			return file;
		} else {
			Log.error("无法创建文件 {}!", new Object[] { path + fileName });
			return null;
		}
	}

	/**
	 * 读取某个文件夹下的所有文件夹和文件（递归）
	 *
	 * @author lh_neu
	 * @param filepath
	 *            文件夹路径
	 * @return 返回一个map，健（folders：文件夹名称、files：文件路径、fileNames：文件名、times：文件修改时间）
	 *         <p>
	 *         返回的信息都是相对路径，例如读取D:\\app下内容，则返回2009、2009\2\test2.xls等相对于D:\\app下的内容
	 */
	public static Map<String, List<String>> readfile(final String filepath) {
		return FileUtil.readfile(filepath, true, "");
	}

	/**
	 * 搜索手机中的文件（只查询根下的文件，未做递归操作，考虑到手机硬件是否能负荷程序的大规模搜索）
	 *
	 * @param filePath
	 *            文件路径，默认是根
	 * @param keyword
	 *            文件名包含的文字(小技巧，输入“.”可以查询目录下所有文件，应文件都是有扩展名的)
	 * @return 找到的文件
	 */
	public static List<String> searchFile(String filePath, final String keyword) {
		if (StringUtils.isEmpty(filePath)) {
			filePath = "/";
		}
		List<String> result = null;
		if (keyword != null) {
			final File[] fileArr = new File(filePath).listFiles(); // 列出根目录下的文件
			if ((fileArr != null) && (fileArr.length > 0)) {
				result = new ArrayList<String>(fileArr.length);
				for (final File f : fileArr) {
					if (!f.isDirectory()) {
						if (f.getName().indexOf(keyword) >= 0) {
							result.add(f.getAbsolutePath());
						}
					} else if (f.isDirectory()) {
						result.addAll(FileUtil.searchFile(filePath + File.separator + f.getName(), keyword));
					}
				}
			}
		}
		return result;
	}

	/**
	 * 获取文件扩展名。例如：
	 * <p>
	 * 输入 -> javadoc.doc
	 * <p>
	 * 输出 -> .doc
	 *
	 * @param fileName
	 *            文件名
	 * @return 文件扩展名
	 */
	public static String getSuffix(final String fileName) {
		if (StringUtils.isNotEmpty(fileName) && StringUtils.isNotEmpty(StringUtils.substringAfterLast(fileName, "."))) {
			return "." + StringUtils.substringAfterLast(fileName, ".");
		}
		return "";
	}

	/**
	 * 根据扩展名生成一个临时文件名。例如：
	 * <p>
	 * 输入 -> doc
	 * <p>
	 * 输出 -> 1306387203019166.doc
	 *
	 * @author lh_neu
	 * @param suffix
	 *            扩展名。前面不带点
	 * @return 临时文件名
	 */
	public static String getRandomFileName(String suffix) {
		final IdWorker idWorker = new IdWorker(new Random().nextInt(30) + 1, 1);
		suffix = StringUtils.lowerCase(StringUtils.trimToEmpty(suffix));
		// 生成一个文件名
		if (StringUtils.isNotEmpty(suffix)) {
			if (StringUtils.indexOf(suffix, ".") == 0) {
				return idWorker.nextId() + suffix;
			} else {
				return idWorker.nextId() + "." + suffix;
			}
		} else {
			return "";
		}
	}

	/**
	 * 重命名文件夹
	 *
	 * @param path
	 *            文件路径
	 * @param fileNewName
	 *            新名字
	 * @return 新的文件夹路径
	 */
	public synchronized static String renameFile(final String path, final String fileNewName) {
		if (StringUtils.isEmpty(path) || StringUtils.isEmpty(fileNewName)) {
			return null;
		}
		if (!FileUtil.exists(path)) {
			return null;
		}
		final File file = new File(path); // 指定文件名及路径

		final String pathNoEndSeparator = FileUtil.getFullPathNoEndSeparator(path);
		final String newPath = FileUtil.getFullPathNoEndSeparator(
				pathNoEndSeparator.substring(0, pathNoEndSeparator.lastIndexOf(File.separator) + 1) + fileNewName);
		file.renameTo(new File(newPath)); //改名
		return file.getAbsolutePath();
	}

	/**
	 * 重命名文件夹
	 *
	 * @param path
	 *            文件路径
	 * @param folderNewName
	 *            最底层目录的新名字
	 * @return 新的文件夹路径
	 */
	public synchronized static String renameFolder(String path, final String folderNewName) {
		if (StringUtils.isEmpty(path) || StringUtils.isEmpty(folderNewName)) {
			return null;
		}
		if (!FileUtil.exists(path)) {
			return null;
		}
		path = FilenameUtils.normalize(path);
		final String pathNoEndSeparator = FileUtil.getFullPathNoEndSeparator(path);
		final String newPath = FileUtil.getFullPathNoEndSeparator(
				pathNoEndSeparator.substring(0, pathNoEndSeparator.lastIndexOf(File.separator) + 1) + folderNewName
						+ File.separator);
		// 若名称为改变就不用重命名了
		if (pathNoEndSeparator.equalsIgnoreCase(newPath)) {
			return newPath;
		}
		// 若新名称的文件已经存在了，则删除
		FileUtil.delFile(newPath);
		if (new File(path).renameTo(new File(newPath))) {
			return newPath;
		}
		return null;

	}

	/**
	 * 获取最后一级文件夹文件夹路径
	 * <p>
	 * 修订FilenameUtils.getFullPathNoEndSeparator方法，递归去掉所有空目录
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao\\\\\\\\\\
	 * <p>
	 * 返回：D:\\opt\\webapps\\baoxiao
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao
	 * <p>
	 * 返回：D:\\opt\\webapps\\baoxiao
	 *
	 * @param path
	 *            文件夹
	 * @return 文件夹路径
	 */
	public static String getFullPathNoEndSeparator(final String path) {
		if (File.separator.equals(StringUtils.right(path, 1)) || "/".equals(StringUtils.right(path, 1))) {
			return FileUtil.getFullPathNoEndSeparator(FilenameUtils.getFullPathNoEndSeparator(path));
		}
		return path;
	}

	/**
	 * 获取最后一级文件夹名称
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao\\
	 * <p>
	 * 返回：baoxiao
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao
	 * <p>
	 * 返回：webapps
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao\\index.jsp
	 * <p>
	 * 返回：index.jsp
	 *
	 * @param filename
	 *            文件路径
	 * @return 最后一级文件夹名称
	 */
	public static String getLastFolderPathNoEndSeparator(final String filename) {
		final String path = FileUtil.getFullPathNoEndSeparator(filename);
		final int index = FilenameUtils.indexOfLastSeparator(path);
		// 如果是根目录 Returns the length of the filename prefix, such as C:/ or ~/.
		if (index < 0) {
			return filename.substring(0, FilenameUtils.getPrefixLength(filename));
		}
		return path.substring(index + 1);
	}

	/**
	 * 获取文件名称中的路径部分
	 * <p>
	 * 例如：D:\\opt\\webapps\\baoxiao\\index.jsp
	 * <p>
	 * 返回：D:\\opt\\webapps\\baoxiao\\
	 * <p>
	 * 例如：/opt/webapps/index.jsp
	 * <p>
	 * 返回：/opt/webapps/
	 *
	 * @param filename
	 *            文件名
	 * @return 路径
	 */
	public static String getFolderPathByFile(final String filename) {
		final String path = FileUtil.getFullPathNoEndSeparator(filename);
		final int index = FilenameUtils.indexOfLastSeparator(path);
		// 如果是根目录 Returns the length of the filename prefix, such as C:/ or ~/.
		if (index < 0) {
			return filename.substring(0, FilenameUtils.getPrefixLength(filename));
		}
		return path.substring(0, index + 1);
	}

	/**
	 * 复制单个文件
	 *
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf.txt
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf.txt
	 * @param srcCoding
	 *            String 源文件字符集
	 * @param destCoding
	 *            String 目的文件字符集
	 * @throws SystemErrorException
	 *             Excetion
	 */
	public synchronized static void copyFile(final String oldPath, final String srcCoding, final String newPath,
			final String destCoding) throws SystemErrorException {
		BufferedReader br = null;
		BufferedWriter bw = null;

		InputStream inStream = null;
		FileOutputStream fs = null;
		try {
			final File oldfile = new File(oldPath);
			final File newfile = new File(newPath);
			if (!newfile.exists() || !newfile.isFile()) {
				newfile.createNewFile();
			}

			if (oldfile.exists()) { // 文件存在时
				inStream = new FileInputStream(oldfile);
				if (StringUtils.isNotEmpty(srcCoding)) {
					br = new BufferedReader(new InputStreamReader(inStream, srcCoding));
				} else {
					br = new BufferedReader(new InputStreamReader(inStream));
				}

				fs = new FileOutputStream(newfile);

				if (StringUtils.isNotEmpty(destCoding)) {
					bw = new BufferedWriter(new OutputStreamWriter(fs, destCoding));
				} else {
					bw = new BufferedWriter(new OutputStreamWriter(fs));
				}
				final int len = 1024 * 5;
				final char[] cbuf = new char[len];
				int ret = 0;
				while ((ret = br.read(cbuf, 0, len)) != -1) {
					bw.write(cbuf, 0, ret);
					bw.flush();
				}
			}
		} catch (final IOException e) {
			Log.error(e.getMessage());
			e.printStackTrace();
		} catch (final Exception e) {
			Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
			throw new SystemErrorException(e.getMessage());
		} finally {
			try {
				if (inStream != null) {
					inStream.close();
				}
				if (fs != null) {
					fs.close();
				}
				if (br != null) {
					br.close();
				}
				if (bw != null) {
					bw.close();
				}

			} catch (final IOException e) {
				Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
			}
		}
	}

	/**
	 * 复制单个Zip文件
	 *
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf.txt
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf.txt
	 * @param srcCoding
	 *            String 源文件字符集
	 * @param destCoding
	 *            String 目的文件字符集
	 * @throws SystemErrorException
	 *             Excetion
	 */
	//	@SuppressWarnings("rawtypes")
	//	public synchronized static void copyZip(final String oldPath, final String srcCoding, final String newPath,
	//			final String destCoding) throws SystemErrorException {
	//		ZipFile srcZipFile = null;
	//		ZipOutputStream zos = null;
	//		BufferedInputStream bis = null;
	//		try {
	//			final File srcFile = new File(oldPath);
	//			final File newFile = new File(newPath);
	//			if (!newFile.exists() || !newFile.isFile()) {
	//				newFile.createNewFile();
	//			}
	//			if (srcFile.exists()) { // 文件存在时
	//				srcZipFile = new ZipFile(srcFile);
	//				zos = new ZipOutputStream(new FileOutputStream(newFile));
	//				zos.setEncoding(destCoding);
	//				Enumeration srcEntries = srcZipFile.getEntries();
	//				while (srcEntries.hasMoreElements()) {
	//					ZipEntry entry = (ZipEntry) srcEntries.nextElement();
	//					ZipEntry newEntry = new ZipEntry(entry.getName());
	//					zos.putNextEntry(newEntry);
	//					bis = new BufferedInputStream(srcZipFile.getInputStream(entry));
	//					while (bis.available() > 0) {
	//						zos.write(bis.read());
	//					}
	//					zos.closeEntry();
	//					bis.close();
	//				}
	//			}
	//		} catch (final IOException e) {
	//			Log.error(e.getMessage());
	//			e.printStackTrace();
	//		} catch (final Exception e) {
	//			Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
	//			throw new SystemErrorException(e.getMessage());
	//		} finally {
	//			try {
	//				if (srcZipFile != null) {
	//					srcZipFile.close();
	//				}
	//				if (zos != null) {
	//					zos.finish();
	//					zos.close();
	//				}
	//			} catch (final IOException e) {
	//				Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
	//			}
	//		}
	//	}

	/**
	 * 复制单个文件
	 *
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf.txt
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf.txt
	 * @throws SystemErrorException
	 *             Excetion
	 */
	public synchronized static void copyFile(final String oldPath, final String newPath) throws SystemErrorException {
		InputStream inStream = null;
		FileOutputStream fs = null;
		try {
			int byteread = 0;
			final File oldfile = new File(oldPath);
			final File newfile = new File(newPath);
			if (!newfile.exists() || !newfile.isFile()) {
				new File(FileUtil.getFolderPathByFile(newPath)).mkdirs();
				newfile.createNewFile();
			}
			if (oldfile.exists()) { // 文件存在时
				// svn 文件不处理
				if (!"svn-base".equalsIgnoreCase(FileUtil.getSuffix(oldfile.getName()))) {
					inStream = new FileInputStream(oldPath); // 读入原文件
					fs = new FileOutputStream(newfile);
					final byte[] buffer = new byte[2048];
					while ((byteread = inStream.read(buffer)) != -1) {
						fs.write(buffer, 0, byteread);
					}
					fs.flush();
				}
			}
		} catch (final Exception e) {
			Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
			throw new SystemErrorException(e.getMessage());
		} finally {
			try {
				if (inStream != null) {
					inStream.close();
				}
				if (fs != null) {
					fs.close();
				}
			} catch (final IOException e) {
				Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
			}
		}
	}

	/**
	 * 复制整个文件夹内容
	 *
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf/ff
	 */
	public synchronized static void copyFolder(final String oldPath, final String newPath) {
		FileInputStream input = null;
		FileOutputStream output = null;

		// 原文件夹不存在，直接退出
		final File a = new File(oldPath);
		if (!a.isDirectory() && !a.exists()) { // 判断文件夹是否存在
			return;
		}
		final String[] file = a.list();
		if (file == null || file.length == 0) {
			return;
		}

		// 如果文件夹不存在 则建立新文件夹
		FileUtil.makeDir(newPath);

		File temp = null;
		for (final String element : file) {
			if (oldPath.endsWith(File.separator)) {
				temp = new File(oldPath + element);
			} else {
				temp = new File(oldPath + File.separator + element);
			}

			if (temp.isFile()) {
				// svn 文件不处理
				if (!"svn-base".equalsIgnoreCase(FileUtil.getSuffix(temp.getName()))) {
					try {
						input = new FileInputStream(temp);
						output = new FileOutputStream(newPath + File.separator + (temp.getName()).toString());
						final byte[] b = new byte[1024 * 5];
						int len;
						while ((len = input.read(b)) != -1) {
							output.write(b, 0, len);
						}
						output.flush();
					} catch (final Exception e) {
						Log.error(e.getMessage() + "  oldPath --> " + oldPath + "   newPath --> " + newPath);
					} finally {
						try {
							if (output != null) {
								output.close();
							}
							output = null;
							if (input != null) {
								input.close();
							}
							input = null;
						} catch (final IOException e) {
							Log.error(e.getMessage());
						}
					}
				}
			}
			if (temp.isDirectory()) { // 如果是子文件夹
				// svn 文件不进行操作
				if (!".svn".equalsIgnoreCase(element)) {
					FileUtil.copyFolder(oldPath + File.separator + element, newPath + File.separator + element);
				}
			}
		}

	}

	/**
	 * 移动文件
	 *
	 * @param oldFileName
	 *            源文件完整路径
	 * @param newPath
	 *            目的目录完整路径
	 * @return 文件移动成功返回true，否则返回false
	 */
	public synchronized static boolean moveFile(final String oldFileName, final String newPath) {
		final File srcFile = new File(oldFileName);
		if (!srcFile.exists() || !srcFile.isFile()) {
			return false;
		}
		// svn 文件不处理
		if ("svn-base".equalsIgnoreCase(FileUtil.getSuffix(srcFile.getName()))) {
			return true;
		}
		final File destDir = new File(newPath);
		if (!destDir.exists()) {
			destDir.mkdirs();
		}
		return srcFile.renameTo(new File(newPath + File.separator + srcFile.getName()));
	}

	/**
	 * 移动目录
	 *
	 * @param oldPath
	 *            源目录完整路径
	 * @param newPath
	 *            目的目录完整路径
	 * @return 目录移动成功返回true，否则返回false
	 */
	public synchronized static boolean moveDirectory(final String oldPath, final String newPath) {
		final File srcDir = new File(oldPath);
		if (!srcDir.exists() || !srcDir.isDirectory()) {
			return false;
		}

		final File destDir = new File(newPath);
		if (!destDir.exists()) {
			destDir.mkdirs();
		}

		/**
		 * 如果是文件则移动，否则递归移动文件夹。删除最终的空源文件夹 注意移动文件夹时保持文件夹的树状结构
		 */
		final File[] sourceFiles = srcDir.listFiles();
		for (final File sourceFile : sourceFiles) {
			if (sourceFile.isFile()) {
				FileUtil.moveFile(sourceFile.getAbsolutePath(), destDir.getAbsolutePath());
			} else if (sourceFile.isDirectory()) {
				// svn 文件不进行操作
				if (!".svn".equalsIgnoreCase(sourceFile.getName())) {
					FileUtil.moveDirectory(sourceFile.getAbsolutePath(),
							destDir.getAbsolutePath() + File.separator + sourceFile.getName());
				}
			}
		}
		return srcDir.delete();
	}

	/**
	 * 读取文件内容
	 *
	 * @param filePath
	 *            文件名称及路径
	 * @return 文件内容
	 */
	public static String readFile(final String filePath) {
		return FileUtil.readFile(filePath, null, null);
	}

	/**
	 * 读取文件内容
	 *
	 * @param filePath
	 *            文件名称及路径
	 * @param map
	 *            待替换的标签
	 * @return 文件内容
	 */
	public static String readFile(final String filePath, final Map<String, String> map) {
		return FileUtil.readFile(filePath, null, map);
	}

	/**
	 * 读取文件内容
	 *
	 * @param filePath
	 *            文件名称及路径
	 * @param encode
	 *            字符集
	 * @param map
	 *            待替换的标签
	 * @return 文件内容
	 */
	public static String readFile(final String filePath, final String encode, final Map<String, String> map) {
		InputStreamReader read = null;
		FileInputStream fos = null;
		File file = null;
		try {
			file = new File(filePath);
			if (!file.exists()) {
				return null;
			}
			fos = new FileInputStream(file);
			if (StringUtils.isNotEmpty(encode)) {
				read = new InputStreamReader(fos, encode);
			} else {
				read = new InputStreamReader(fos);
			}
			final StringBuffer str = new StringBuffer("");
			char[] strtemp = new char[1000];
			while ((read.read(strtemp)) > -1) {
				str.append(strtemp);
				strtemp = new char[1000];
			}

			String content = str.toString();
			if (map != null && !map.isEmpty()) {
				final Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
				while (iter.hasNext()) {
					final Map.Entry<String, String> entry = iter.next();
					content = content.replaceAll(entry.getKey(), entry.getValue());
				}
			}

			return content;
		} catch (final Exception e) {
			Log.error(e.getMessage() + "  filePath --> " + filePath);
		} finally {
			try {
				if (read != null) {
					read.close();
				}
				if (fos != null) {
					fos.close();
				}
				file = null;
			} catch (final Exception e) {
				Log.error(e.getMessage());
			}
		}
		return null;
	}

	/**
	 * 读取小文件内容
	 *
	 * @param filePath
	 *            文件名称及路径
	 * @return 文件内容
	 */
	public static String readSmallFile(final String filePath) {
		BufferedReader in = null;
		File file = null;
		try {
			file = new File(filePath);
			if (!file.exists()) {
				return null;
			}

			final StringBuilder sb = new StringBuilder("");
			try {
				// 读取字符文件
				in = new BufferedReader(new FileReader(file));

				// 为什么单独在这里加上try块而不是直接使用外边的try块？
				// 需要考虑这么一种情况，如果文件没有成功打开，则finally关闭文件会出问题
				String s;
				while ((s = in.readLine()) != null) {
					sb.append(s + "\n");
				}
			} catch (final IOException e) {
				e.printStackTrace();
			}

			return sb.toString();
		} catch (final Exception e) {
			Log.error(e.getMessage() + "  filePath --> " + filePath);
		} finally {
			try {
				if (in != null) {
					in.close();
				}
				file = null;
			} catch (final Exception e) {
				Log.error(e.getMessage());
			}
		}
		return null;
	}

	/**
	 * 写文件
	 *
	 * @param fileName
	 *            文件名称
	 * @param content
	 *            内容
	 * @param isAppend
	 *            是否追加内容
	 * @param map
	 *            待替换的标签
	 * @throws IOException
	 *             异常
	 */
	public static void writeFile(final String fileName, final String content, final boolean isAppend,
			final Map<String, String> map) throws IOException {
		FileUtil.writeFile(fileName, null, content, isAppend, map);
	}

	/**
	 * 写文件
	 * <p>
	 * 1.写文件1000行的时候，FileOutputStream执行耗时:46 豪秒 BufferedOutputStream执行耗时:31 豪秒 FileWriter执行耗时:15 豪秒
	 * <p>
	 * 2.写文件10000行的时候，FileOutputStream执行耗时:188 豪秒 BufferedOutputStream执行耗时:32 豪秒 FileWriter执行耗时:16 豪秒
	 * <p>
	 * 3.写文件100000行的时候，FileOutputStream执行耗时:1266 豪秒 BufferedOutputStream执行耗时:125 豪秒 FileWriter执行耗时:93 豪秒
	 * <p>
	 * 4.写文件1000000行的时候，FileOutputStream执行耗时:12063 豪秒 BufferedOutputStream执行耗时:1484 豪秒 FileWriter执行耗时:969 豪秒
	 *
	 * @param fileName
	 *            文件名称
	 * @param encode
	 *            字符集，默认字符集UTF-8
	 * @param content
	 *            内容
	 * @param isAppend
	 *            是否追加内容
	 * @param map
	 *            待替换的标签
	 * @throws IOException
	 *             异常
	 */
	public static void writeFile(final String fileName, final String encode, final String content,
			final boolean isAppend, final Map<String, String> map) {

		if (StringUtils.isEmpty(fileName)) {
			return;
		}

		//		new Thread() {
		//			@Override
		//			public void run() {
		FileWriterWithEncoding fw = null;
		try {
			// 生成文件
			final File newfile = new File(fileName);
			if (!newfile.exists() || !newfile.isFile()) {
				newfile.getParentFile().mkdirs();
				newfile.createNewFile();
			}

			// 复制一个，避免修改原数据
			String fileContent = content;
			if (StringUtils.isNotEmpty(fileContent) && map != null && !map.isEmpty()) {
				final Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
				while (iter.hasNext()) {
					final Map.Entry<String, String> entry = iter.next();
					fileContent = fileContent.replaceAll(entry.getKey(), entry.getValue());
				}
			}

			// 写文件，ture表明追加记录
			fw = new FileWriterWithEncoding(fileName, StringUtils.isEmpty(encode) ? "UTF-8" : encode, isAppend);
			fw.write(fileContent);
			fw.flush(); // 清理缓存
		} catch (final IOException e) {
			Log.error(e.getMessage() + " --> " + fileName);
		} finally {
			try {
				if (fw != null) {
					fw.close();
					fw = null;
				}
			} catch (final IOException e) {
				Log.error(e.getMessage());
			}
		}
		//			}
		//		}.start();
	}

	/**
	 * GZip方式写文件
	 *
	 * @param fileName
	 *            文件名称
	 * @param encode
	 *            字符集，默认字符集UTF-8
	 * @param content
	 *            内容
	 * @param isAppend
	 *            是否追加内容
	 * @param map
	 *            待替换的标签
	 * @throws IOException
	 *             异常
	 */
	@SuppressWarnings("unused")
	public static void writeFileByGZip(final String fileName, final String encode, final String content,
			final boolean isAppend, final Map<String, String> map) throws IOException {

		if (StringUtils.isEmpty(fileName)) {
			return;
		}

		// 1. 先将文件写入
		FileUtil.writeFile(fileName, encode, content, isAppend, map);

		// 2. 再读取出来进行压缩
		// 读取资源文件流
		final File file = new File(fileName);
		if (!file.exists()) {
			return;
		}

		InputStream resource = null;
		try {
			resource = new FileInputStream(file);
		} catch (final FileNotFoundException e) {
			return;
		}
		if (resource == null) {
			return;
		}
		BufferedReader in = null;
		try {
			final InputStreamReader read = new InputStreamReader(resource, encode);
			if (read == null) {
				return;
			}
			in = new BufferedReader(read);
			if (in == null) {
				return;
			}
			boolean done = false;
			boolean isContinue = false;
			boolean isBeforeContinue = false;
			final StringBuilder command = new StringBuilder();
			String line = null;
			while (!done) {
				while (true) {
					line = in.readLine();
					if (line == null) {
						done = true;
						break;
					}
					// 设置需要跳过的行（注释的行都去掉）
					if (line.trim().startsWith("//")) {
						isContinue = true;
					}
					if (line.trim().startsWith("/**")) {
						isContinue = true;
						isBeforeContinue = true;
					}
					if (line.trim().startsWith("*") && isBeforeContinue) {
						isContinue = true;
					}
					if (line.trim().startsWith("*/")) {
						isContinue = true;
						isBeforeContinue = false;
					}

					if (isContinue) {
						isContinue = false;
						continue;
					}
					command.append(line);
				}
			}

			if (!command.toString().equals("")) {
				FileUtil.writeFile(fileName, encode, command.toString(), isAppend, map);
			}

		} catch (final IOException e) {
			Log.error(e.getMessage());
			return;
		} finally {
			try {
				if (in != null) {
					in.close();
				}
				if (resource != null) {
					resource.close();
				}
			} catch (final Exception e) {
				Log.error(e.getMessage(), e);
			}

		}
	}

	/**
	 * 替换文件中的标签
	 *
	 * @param filePath
	 *            文件名
	 * @param encode
	 *            字符集
	 * @param map
	 *            待替换的标签
	 * @throws IOException
	 *             异常
	 */
	public static void replaceFileContent(final String filePath, final String encode, final Map<String, String> map)
			throws IOException {
		if (StringUtils.isEmpty(filePath) || map == null || map.isEmpty()) {
			return;
		}
		// 替换机构代码
		String content = FileUtil.readFile(filePath, encode, null);
		if (StringUtils.isEmpty(content)) {
			return;
		}
		final Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
		while (iter.hasNext()) {
			final Map.Entry<String, String> entry = iter.next();
			content = content.replaceAll(entry.getKey(), entry.getValue());
		}

		FileUtil.writeFile(filePath, encode, StringUtils.trimToEmpty(content), false, null);
	}

	/**
	 * 通过文件的路径得到该文件的base64的二进制文件内容
	 *
	 * @param filePath
	 *            文件
	 * @return 字节
	 */
	public static byte[] fileToByte(final String filePath) {
		byte[] file = null;
		if (FileUtil.exists(filePath)) {
			RandomAccessFile rf = null;
			try {
				rf = new RandomAccessFile(filePath, "r");
				final int total = (int) rf.length();
				file = new byte[total];
				rf.read(file);
				return file;
			} catch (final IOException e) {
				e.printStackTrace();
			} catch (final OutOfMemoryError er) {
				throw er;
			} finally {
				try {
					if (rf != null) {
						rf.close();
					}
				} catch (final IOException e) {
					Log.error(e.getMessage());
				}
			}
		}
		return file;
	}

	/**
	 * 通过文件的路径及base64的二进制文件内容生成文件
	 *
	 * @param data
	 *            字节
	 * @param filePath
	 *            文件
	 */
	public static void bytetoFile(final byte[] data, final String filePath) {
		if (StringUtils.isEmpty(filePath)) {
			return;
		}
		final File f = new File(filePath);
		try {
			if (!f.exists()) {
				f.createNewFile(); // 创建文件
			}

			FileUtil.outBytes(f, data, 0, data.length, false);
		} catch (final IOException e) {
			Log.error(e.getMessage());
		}
	}

	/**
	 * @param dest
	 *            File
	 * @param data
	 *            final byte[]
	 * @param off
	 *            int
	 * @param len
	 *            int
	 * @param append
	 *            boolean
	 * @throws IOException
	 *             读写异常
	 */
	private static void outBytes(final File dest, final byte[] data, final int off, final int len, final boolean append)
			throws IOException {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(dest, append);
			out.write(data, off, len);
			out.flush();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
			} catch (final IOException e) {
				Log.error(e.getMessage());
			}
		}
	}

	/**
	 * 读取文件
	 *
	 * @param filePath
	 *            文件路径
	 * @return 二进制
	 */
	public synchronized static byte[] handleInputStream(final String filePath) {
		if (StringUtils.isEmpty(filePath)) {
			return null;
		}
		InputStream in = null;
		try {
			in = new FileInputStream(filePath);
			final byte[] data = FileUtil.handleInputStream(in);
			return data;
		} catch (final Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (final IOException e) {
				Log.error(e.getMessage());
			}
		}
		return null;
	}

	/**
	 * 循环从流中读取文件到二进制中 <教授算法>
	 *
	 * @author lh_neu
	 * @param stream
	 *            数据流
	 * @return 二进制
	 * @throws IOException
	 *             Exception
	 */
	public synchronized static byte[] handleInputStream(final InputStream stream) throws IOException {
		// 由于输入流无法计算总字节数，只能分块读写
		byte[] tempData = new byte[100];
		final Vector<byte[]> vec = new Vector<byte[]>();
		long contentLen = 0;
		// 总内容长度
		int tempLen = 0;
		// 临时长度
		int k = stream.read();
		while (k != -1) {
			contentLen++;
			// 总长度加1
			if (tempLen >= 100) {
				// 一个字节块已经装满
				vec.add(tempData);
				// 加入集合
				tempData = new byte[100];
				// 生成新的字节块
				tempLen = 0;
			}
			tempData[tempLen] = (byte) k;
			tempLen++;
			k = stream.read();
		}
		if (tempLen > 0) {
			// 将剩余的字节加入集合
			final byte[] tempData2 = new byte[tempLen];
			System.arraycopy(tempData, 0, tempData2, 0, tempData2.length);
			vec.add(tempData2);
		}
		// 将字节数组的集合拼接成长字节数组
		final byte[] content = new byte[(int) contentLen];
		int start = 0;
		for (int i = 0; i < vec.size(); i++) {
			final byte[] data = vec.elementAt(i);
			System.arraycopy(data, 0, content, start, data.length);
			start += data.length;
		}
		return content;
	}

	/**
	 * 访问URL并下载文件
	 *
	 * @param ourputFile
	 *            存放地址
	 * @param urlStr
	 *            URL路径
	 */
	public static void getURLResource(final String ourputFile, final String urlStr) {
		FileWriter fw = null;
		PrintWriter pw = null;
		try {
			fw = new FileWriter(ourputFile);
			pw = new PrintWriter(fw);
			final URL resourceUrl = new URL(urlStr);
			final InputStream content = (InputStream) resourceUrl.getContent();
			final BufferedReader in = new BufferedReader(new InputStreamReader(content));
			String line;
			while ((line = in.readLine()) != null) {
				pw.println(line);
			}
			pw.flush();
		} catch (final IOException e) {
			Log.error(e.getMessage());
		} finally {
			try {
				if (pw != null) {
					pw.close();
				}
				if (fw != null) {
					fw.close();
				}
			} catch (final IOException e) {
				Log.error(e.getMessage());
			}
		}
	}

	/**
	 * 读取某个文件夹下的所有文件夹和文件（递归）
	 *
	 * @author lh_neu
	 * @param filepath
	 *            要读取的路径
	 * @param base
	 *            是否是根路径
	 * @param relPath
	 *            如不是根路径需要加上相对路径
	 * @return 返回一个map，健（folders：文件夹名称、files：文件路径、fileNames：文件名、times：文件修改时间）
	 *         <p>
	 *         返回的信息都是相对路径，例如读取D:\\app下内容，则返回2009、2009\2\test2.xls等相对于D:\\app下的内容
	 */
	private static Map<String, List<String>> readfile(final String filepath, final boolean base, final String relPath) {
		if (base) {
			Log.debug("读取路径：" + filepath);
			FileUtil.fileMap = new HashMap<String, List<String>>(2);
			FileUtil.folders = new ArrayList<String>(0);
			FileUtil.files = new ArrayList<String>(0);
			FileUtil.fileNames = new ArrayList<String>(0);
			FileUtil.times = new ArrayList<String>(0);
		}
		try {
			final File file = new File(filepath);
			if (!file.isDirectory()) {
				// svn 文件不处理
				if (!"svn-base".equalsIgnoreCase(FileUtil.getSuffix(file.getName()))) {
					FileUtil.fileNames.add(file.getName());
					FileUtil.files.add(relPath + file.getName());
					FileUtil.times
							.add(LocalDateUtil.dateTimeToStr(LocalDateUtil.getMillisToDateTime(file.lastModified()))); // 最后一次改变文件的时间
				}
			} else if (file.isDirectory()) {
				// svn 文件不处理
				if (!".svn".equalsIgnoreCase(FileUtil.getSuffix(file.getName()))) {
					if (!base) {
						FileUtil.folders.add(relPath + file.getName());
					}
					final String[] filelist = file.list();
					for (final String element : filelist) {
						final File readfile = new File(filepath + File.separator + element);
						if (!readfile.isDirectory()) {
							if (base) {
								FileUtil.files.add(readfile.getName());
							} else {
								FileUtil.files.add(relPath + file.getName() + File.separator + readfile.getName());
							}
							FileUtil.fileNames.add(readfile.getName());
							FileUtil.times.add(LocalDateUtil
									.dateTimeToStr(LocalDateUtil.getMillisToDateTime(readfile.lastModified()))); // 最后一次改变文件的时间
						} else if (readfile.isDirectory()) {
							if (base) {
								FileUtil.readfile(filepath + File.separator + element, false, "");
							} else {
								FileUtil.readfile(filepath + File.separator + element, false,
										relPath + file.getName() + File.separator);
							}
						}
					}
				}
			}
		} catch (final Exception e) {
			Log.error(e.getMessage() + "  --> " + filepath);
		}
		FileUtil.fileMap.put("folders", FileUtil.folders);
		FileUtil.fileMap.put("files", FileUtil.files);
		FileUtil.fileMap.put("fileNames", FileUtil.fileNames);
		FileUtil.fileMap.put("times", FileUtil.times);
		return FileUtil.fileMap;
	}

	/**
	 * 解决下载附件时，中文文件名乱码问题
	 * <P>
	 * response.setHeader("Content-Disposition", "attachment;filename=" + FileUtil.downloadFileName(request,
	 * att.getOldFileName()));
	 *
	 * @param request
	 *            HttpServletRequest
	 * @param oldName
	 *            原文件名
	 * @return 处理后的文件名
	 */
	public static String downloadFileName(final HttpServletRequest request, final String oldName) {
		//		try {
		//			// 自动获取当前IE的编码
		//			//			String encoding = "UTF-8";
		//			//			if (encoding == null) {
		//			//				encoding = Charset.defaultCharset().name();
		//			//			}
		//
		//			String browName = "=?UTF-8?B?" + EncodeUtils.encodeBase64Str(oldName, "UTF-8") + "?=";
		//
		//			//处理换行符（如果存在）
		//			final StringReader sr = new StringReader(browName);
		//			final BufferedReader br = new BufferedReader(sr);
		//			String line = null;
		//			String temp = "";
		//			while ((line = br.readLine()) != null) {
		//				temp += line;
		//			}
		//			browName = temp;
		//			//如果是IE
		//			final String clientInfo = request.getHeader("User-agent");
		//			if (clientInfo != null) {
		//
		//				if (clientInfo.indexOf("MSIE") > 0) {
		//					//IE采用URLEncoder方式处理
		//					if (clientInfo.indexOf("MSIE 6") > 0 || clientInfo.indexOf("MSIE 5") > 0) { //IE6，用GBK，此处实现由局限性
		//						browName = new String(oldName.getBytes("GBK"), "ISO8859-1");
		//					} else { //ie7+用URLEncoder方式
		//						browName = java.net.URLEncoder.encode(oldName, "UTF-8");
		//						browName = browName.replaceAll("\\+", " ");
		//					}
		//				} else if (clientInfo.indexOf("Firefox") > 0) {
		//					// 火狐必须是ISO-8859-1
		//					browName = new String(browName.getBytes("UTF-8"), "ISO-8859-1");
		//				}
		//			}
		//			return browName;
		//		} catch (final Exception e) {
		//			Log.error(e.getMessage());
		//		}
		//		return oldName;
		// 中文名称跨浏览器兼容问题 2015年1月23日10:24:29 hxo
		String filename = null;
		if (request == null) {
			try {
				filename = java.net.URLEncoder.encode(oldName, "UTF-8");

				filename = StringUtils.replace(filename, "+", "%20"); //替换空格
			} catch (final UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else {
			final String agent = request.getHeader("USER-AGENT");
			try {
				if (null != agent) {
					if (-1 != agent.indexOf("Firefox")) { //Firefox
						filename = "=?UTF-8?B?"
								+ (new String(
										org.apache.commons.codec.binary.Base64.encodeBase64(oldName.getBytes("UTF-8"))))
								+ "?=";
					} else if (-1 != agent.indexOf("Chrome")) { //Chrome
						filename = new String(oldName.getBytes(), "ISO8859-1");
					} else { //IE

						filename = java.net.URLEncoder.encode(oldName, "UTF-8");

						filename = StringUtils.replace(filename, "+", "%20"); //替换空格
					}
				} else {
					filename = oldName;
				}
			} catch (final UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		return filename;
	}

	/**
	 * 读取资源文件
	 *
	 * @author lh_neu
	 * @Date 2009-6-5 上午10:56:30
	 * @param filePath
	 *            资源文件路径
	 * @param key
	 *            要读取的键
	 * @return 读取后的值
	 */
	public static String getProperties(final String filePath, final String key) {
		ClassLoader cl = null;
		InputStream is = null;
		Properties properties = null;
		try {
			cl = Thread.currentThread().getContextClassLoader();
			is = cl.getResourceAsStream(filePath);
			properties = new Properties();
			properties.load(is);
			return properties.getProperty(key);
		} catch (final IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (final IOException e) {
				e.printStackTrace();
			}
			properties = null;
			cl = null;
		}
		return "";
	}

	/**
	 * 访问URL并下载文件
	 *
	 * @param fileUrl
	 *            URL路径
	 * @param ourputFile
	 *            存放地址
	 * @return 是否成功
	 * @throws SystemErrorException
	 *             系统异常
	 */
	public static boolean saveUrlAs(final String fileUrl, final String ourputFile) throws SystemErrorException {
		if (StringUtils.isEmpty(fileUrl) || StringUtils.isEmpty(ourputFile)) {
			return false;
		}

		FileUtil.makeDir(FileUtil.getFolderPathByFile(ourputFile));

		//此方法只能用户HTTP协议
		HttpURLConnection connection = null;
		DataInputStream in = null;
		DataOutputStream out = null;
		try {
			final URL url = new URL(fileUrl);
			connection = (HttpURLConnection) url.openConnection();
			in = new DataInputStream(connection.getInputStream());
			out = new DataOutputStream(new FileOutputStream(ourputFile));
			final byte[] buffer = new byte[1024];
			int count = 0;
			while ((count = in.read(buffer)) > 0) {
				out.write(buffer, 0, count);
			}

			out.flush();
			return true;
		} catch (final Exception e) {
			if (e.getMessage().indexOf("拒绝连接") >= 0) {
				throw new SystemErrorException("远程链接[" + fileUrl + "]禁止访问!");
			} else {
				Log.error(e.getMessage(), e);
				throw new SystemErrorException("读取文件[" + fileUrl + "]失败。");
			}
		} finally {
			if (out != null) {
				try {
					out.close();
					out = null;
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
			if (in != null) {
				try {
					in.close();
					in = null;
				} catch (final IOException e) {
					e.printStackTrace();
				}
			}
			connection = null;
		}
	}

	/**
	 * 根据参数生成KEY
	 *
	 * @param shareCode
	 *            共享码
	 */
	private static Key getKey(final String shareCode) {
		if (StringUtils.isEmpty(shareCode)) {
			return null;
		}
		try {
			final KeyGenerator _generator = KeyGenerator.getInstance("DES");
			_generator.init(new SecureRandom(shareCode.getBytes()));
			return _generator.generateKey();
		} catch (final Exception e) {
			throw new RuntimeException("Error initializing SqlMap class. Cause: " + e);
		}
	}

	/**
	 * 文件file进行加密并保存目标文件destFile中
	 *
	 * @param shareCode
	 *            共享码
	 * @param file
	 *            要加密的文件 如c:/test/srcFile.txt
	 * @param destFile
	 *            加密后存放的文件名 如c:/加密后文件.txt
	 */
	public static void encrypt(final String shareCode, final String file, final String destFile) {
		final Key key = FileUtil.getKey(shareCode);
		CipherInputStream cis = null;
		OutputStream out = null;
		InputStream is = null;
		try {
			final Cipher cipher = Cipher.getInstance("DES");
			// cipher.init(Cipher.ENCRYPT_MODE, getKey());
			cipher.init(Cipher.ENCRYPT_MODE, key);
			is = new FileInputStream(file);
			out = new FileOutputStream(destFile);
			cis = new CipherInputStream(is, cipher);
			final byte[] buffer = new byte[1024];
			int r;
			while ((r = cis.read(buffer)) > 0) {
				out.write(buffer, 0, r);
			}
			out.flush();
		} catch (final Exception e) {
			Log.error(e.getMessage());
			return;
		} finally {
			try {
				if (cis != null) {
					cis.close();
				}
				if (out != null) {
					out.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (final Exception e) {
				Log.error(e.getMessage(), e);
			}

		}
	}

	/**
	 * 文件采用DES算法解密文件
	 *
	 * @param shareCode
	 *            共享码
	 * @param file
	 *            已加密的文件 如c:/加密后文件.txt
	 * @param destFile
	 *            解密后存放的文件名 如c:/ test/解密后文件.txt
	 */
	public static void decrypt(final String shareCode, final String file, final String dest) {
		final Key key = FileUtil.getKey(shareCode);
		OutputStream out = null;
		InputStream is = null;
		CipherOutputStream cos = null;
		try {
			final Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.DECRYPT_MODE, key);
			is = new FileInputStream(file);
			out = new FileOutputStream(dest);
			cos = new CipherOutputStream(out, cipher);
			final byte[] buffer = new byte[1024];
			int r;
			while ((r = is.read(buffer)) >= 0) {
				cos.write(buffer, 0, r);
			}
		} catch (final Exception e) {
			Log.error(e.getMessage());
			return;
		} finally {
			try {
				if (cos != null) {
					cos.close();
				}
				if (out != null) {
					out.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (final Exception e) {
				Log.error(e.getMessage(), e);
			}

		}
	}

	/**
	 * 测试
	 *
	 * @param args
	 *            参数
	 * @throws IOException
	 *             异常
	 */
	public static void main(final String[] args) throws IOException {
		FileUtil.copyFolder("E:\\a", "E:\\b");

		//		FileUtil.encrypt("shareCode", "D:/tempDemo.docx", "D:/tempDemo1.docx"); //加密
		//		FileUtil.decrypt("shareCode", "D:/tempDemo1.docx", "D:/tempDemo2.docx"); //解密
		//
		//		System.out.println(FileUtil.getFolderPathByFile("D:\\test-import.xlsx"));
		//		System.out.println(FileUtil.renameFile("D:\\test-import.xlsx", "test-import.xls"));
		//
		//		FileUtil.getProperties("D:\\openfireResources_zh_CN.properties", "openfireUrl");
		//		try {
		//			copyFile("D:\\hxo\\App\\CTSaaS-Platform-v4.0\\web\\files\\temp\\141957775475586.zip", null,
		//					"D:\\hxo\\App\\CTSaaS-Platform-v4.0\\web\\files\\temp\\复制后的FILE.zip", null);
		//			copyZip("D:\\hxo\\App\\CTSaaS-Platform-v4.0\\web\\files\\temp\\141957775475586.zip", null,
		//					"D:\\hxo\\App\\CTSaaS-Platform-v4.0\\web\\files\\temp\\复制后的ZIP.zip", "UTF-8");
		//		} catch (SystemErrorException e) {
		//			e.printStackTrace();
		//		}
	}
}
